home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_asm
/
68kdis
/
libmtch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-12-02
|
7KB
|
309 lines
/*
* SCCS: @(#)libmtch.c 1.2 11/2/84 14:18:55
* Read library files.
*
***********************************************************************
* This software is copyright of
*
* John M Collins
* 47 Cedarwood Drive
* St Albans
* Herts, AL4 0DN
* England +44 727 57267
*
* and is released into the public domain on the following conditions:
*
* 1. No free maintenance will be guaranteed.
* 2. Nothing may be based on this software without
* acknowledgement, including incorporation of this
* notice.
*
* Notwithstanding the above, the author welcomes correspondence and bug
* fixes.
***********************************************************************
*/
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <a.out.h>
#include <ar.h>
#include <setjmp.h>
#include <ldfcn.h>
#include "unc.h"
long atol();
long lseek();
void bfopen(), bfclose(), nomem();
void rrell2(), markmatch();
char *malloc();
int matchup();
long findstart();
char verbose; /* Tell the world what we are doing */
char *tfnam;
char *cfile;
ef_fids mainfile;
struct commit dreltab;
int donedrel, donebrel;
long trelpos, drelpos, brelpos;
static struct libit currlib = {NULL, NULL, ""};
void lclash(str)
char *str;
{
(void) fprintf(stderr, "Library scan failure - %s\n", str);
(void) fprintf(stderr, "Searching %s\n", cfile);
if (currlib.lf_name[0])
(void) fprintf(stderr, "Member is %s\n", currlib.lf_name);
exit(255);
}
/*
* Find next member.
*/
long nextmemb(filename,lfd)
char *filename;
register struct libit *lfd;
{
struct ar_hdr arbuf;
ldaclose(lfd->ldptr2);
if (ldclose(lfd->ldptr != FAILURE)) /* end of archive */
return -1;
lfd->ldptr = ldopen(filename,lfd->ldptr);
ldahread(lfd->ldptr, (char *)&arbuf);
(void) strncpy(lfd->lf_name, arbuf.ar_name, sizeof(lfd->lf_name));
return 1;
}
/*
* Decode a file name thus -
*
* -lxxx decode as /lib/libxxx.a /usr/lib/libxxx.a etc
* -Lxxx forget "lib" ".a" bit thus -Lcrt0.o
* or read LDPATH environment var to give list of directories as sh
* (default /lib:/usr/lib).
*
* Alternatively treat as normal pathname.
*
* File names may be followed by (membername) if the file is an archive,
* thus
*
* -lc(printf.o)
*
* in which case the specified module is fetched.
*/
struct libit *getfnam(str)
char *str; /* will be expanded to full path name if necessary */
{
char *bp, *ep = NULL, *pathb, *pathe, *fullpath = NULL;
static char *pathn;
extern char *getenv();
char magic[8];
struct ar_hdr arhdr;
LDFILE *ldptr;
if ((bp = strrchr(str, '(')) != NULL &&
(ep = strrchr(str, ')')) != NULL)
*ep = *bp = '\0';
if (str[0] == '-' && (str[1] == 'l' || str[1] == 'L')) {
if (pathn == NULL) {
if ((pathn = getenv("LDPATH")) == NULL)
pathn = "/lib:/usr/lib";
}
fullpath = malloc((unsigned)(strlen(pathn) + strlen(str) + 1));
if (fullpath == NULL)
nomem();
pathb = pathn;
do {
pathe = strchr(pathb, ':');
if (*pathb == ':')
fullpath[0] = '\0';
else {
if (pathe != NULL)
*pathe = '\0';
(void) strcpy(fullpath, pathb);
(void) strcat(fullpath, "/");
if (pathe != NULL)
*pathe = ':';
}
if (str[1] == 'l')
(void) strcat(fullpath, "lib");
(void) strcat(fullpath, &str[2]);
if (str[1] == 'l')
(void) strcat(fullpath, ".a");
if ((ldptr = ldopen(fullpath, NULL)) != NULL)
goto found;
pathb = pathe + 1;
} while (pathe != NULL);
(void) fprintf(stderr, "Unable to locate lib%s.a in %s\n",
&str[2], pathn);
exit(101);
}
else if ((ldptr = ldopen(str, NULL)) == NULL) {
(void) fprintf(stderr, "Cannot open %s\n", str);
exit(102);
}
found:
str = fullpath? fullpath: str;
if (FREAD(magic, sizeof(magic),1,ldptr) != 1 ||
strcmp(magic, ARMAG) != 0) {
if (ep != NULL) {
(void) fprintf(stderr, "%s is not library file\n", str);
exit(103);
}
currlib.ldptr = ldptr;
currlib.ldptr2 = ldaopen(str,ldptr);
currlib.lf_name[0] = '\0';
return &currlib;
}
/*
* It appears to be a library file - see if we want a specific
* one.
*/
if (ep != NULL) {
char *cp;
for (;;) {
if (ldahread(ldptr,&arhdr) == FAILURE) {
(void) fprintf(stderr, "Cannot find member %s in %s\n",
bp+1, str);
exit(103);
}
for ( cp = arhdr.ar_name + sizeof(arhdr.ar_name) - 1;
*cp == ' ';
cp -- ) ;
if (strncmp(bp+1, arhdr.ar_name, cp - arhdr.ar_name + 1) == 0)
break;
if (ldclose(ldptr) != FAILURE) {
(void) fprintf(stderr, "Cannot find member %s in %s\n",
bp+1, str);
exit(103);
}
ldptr = ldopen(str,ldptr);
}
currlib.ldptr = ldptr;
currlib.ldptr2 = ldaopen(str,ldptr);
currlib.lf_name[0] = '\0';
*bp = '(';
*ep = ')';
return &currlib;
}
/*
* Otherwise point to 1st member in library.
*/
if (ldahread(ldptr, &arhdr) == FAILURE) {
(void) fprintf(stderr, "Library %s empty\n", str);
exit(104);
}
currlib.ldptr = ldptr;
currlib.ldptr2 = ldaopen(str,ldptr);
(void) strncpy(currlib.lf_name, arhdr.ar_name, sizeof(currlib.lf_name));
return &currlib;
}
/*
* Process library files.
*/
#define MINTEXT 6
void lscan(nfiles, fnames)
int nfiles;
char **fnames;
{
ef_fids libfile;
register ef_fid ll = &libfile;
register struct libit *clf;
extern symbol dolsymb();
int firstfile;
for (; nfiles > 0; fnames++, nfiles--) {
clf = getfnam(*fnames);
cfile = *fnames;
firstfile = 1;
do {
bfopen(tfnam, ll);
/*
* If file is garbled, silently forget it and go
* on to the next one.
*/
if (!rtext(clf->ldptr, ll))
goto closeit;
if (ll->ef_tsize < MINTEXT)
goto closeit;
if (!rdata(clf->ldptr, ll))
goto closeit;
if (rrell1(clf->ldptr, ll) < 0)
goto closeit;
/*
* If first file in library, find it from
* beginning of main file.
*/
if (firstfile) {
if ((trelpos = findstart(&mainfile, ll)) < 0)
goto closeit;
firstfile = 0;
}
else if (!matchup(&mainfile, ll, trelpos))
goto closeit;
/*
* Found a match.
*/
if (!rsymb(clf->ldptr, dolsymb, ll)) {
(void) fprintf(stderr, "Corrupt file %s\n",
*fnames);
exit(150);
}
donedrel = 0;
donebrel = 0;
rrell2(clf->ldptr, clf->ldptr2, ll);
if (verbose) {
(void) fprintf(stderr, "Found: ");
if (clf->lf_name[0])
(void) fprintf(stderr, "%.14s in ",
clf->lf_name);
(void) fprintf(stderr, "%s\n", *fnames);
}
if (libfile.ef_stvec != NULL) {
free(libfile.ef_stvec);
libfile.ef_stvec = NULL;
libfile.ef_stcnt = 0;
}
dreltab.c_int = 0;
/*
* Start looking next time round
* where last one left off.
*/
markmatch(&mainfile, ll, trelpos);
trelpos += libfile.ef_tsize;
closeit:
bfclose(ll);
} while (nextmemb(cfile,clf) >= 0);
}
}